package fmi.chesstern.game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import fmi.chesstern.pieces.ChessPiece;
import fmi.chesstern.pieces.ChessPieceColor;
import fmi.chesstern.pieces.ChessPieceType;

public abstract class GameBoardState {
	public abstract ChessPiece getPieceAt(BoardField field);
	public abstract boolean hasItBeenMoved(BoardField field);
	public abstract ChessPieceColor getCurrentPlayer();
	public abstract int getBoardSize();
	
	public List<BoardField> getFields() {
		List<BoardField> result = new ArrayList<BoardField>();
		
		for (int i = 0; i < getBoardSize(); i++) {
			for (int j = 0; j < getBoardSize(); j++) {
				result.add(new BoardField(i, j));
			}
		}
		
		return result;
	}
	
	public List<BoardField> getPlayerFields(ChessPieceColor player) {
		List<BoardField> result = new ArrayList<BoardField>();
		
		for (BoardField field : getFields()) {
			if (getPieceAt(field) != null && getPieceAt(field).getColor() == player) {
				result.add(field);
			}
		}
		
		return Collections.unmodifiableList(result);
	}
	
	public boolean isFieldInBoard(BoardField field) {
		return field.getRow() >= 0 && field.getColumn() >= 0
			&& field.getRow() < getBoardSize() && field.getColumn() < getBoardSize();
	}
	
	public boolean isInMate() {
		for (BoardField field : getPlayerFields(getCurrentPlayer())) {
			if (!getPieceAt(field).getValidMoves(this, field).isEmpty()) {
				return false;
			}
		}

		return true;
	}
	
	public boolean isMoveValid(Move move) {
		ChessPiece piece = getPieceAt(move.getFrom());
		
		if (piece == null) {
			return false;
		}
		
		return piece.getValidMoves(this, move.getFrom()).contains(move);
	}
	
	public BoardField getKingPositionOf(ChessPieceColor player) {
		for (BoardField field : getPlayerFields(player)) {
			if (getPieceAt(field).getType() == ChessPieceType.KING) {
				return field;
			}
		}
		
		throw new IllegalStateException();
	}
}
